﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;

namespace Jmr.Cryptography
{
	public class HashUtility
	{
		public enum CryptoAlgorithmType
		{
			SHA1,
			SHA256,
#if(!SILVERLIGHT)
			MD5,
			SHA384,
			SHA512
#endif
		}

		public static string CreateRandomSalt(int saltSize)
		{
			RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
			byte[] buff = new byte[saltSize];
			rng.GetBytes(buff);
			return Convert.ToBase64String(buff);
		}

		public static string CreatePasswordHash(string salt, string password)
		{
			return CreatePasswordHash(salt, password, CryptoAlgorithmType.SHA1);
		}

		public static string CreatePasswordHash(string salt, string password, CryptoAlgorithmType algoType)
		{
			string saltAndPwd = String.Concat(password, salt);
			string hashedPwd = GetHashedValue(saltAndPwd, algoType);
			hashedPwd = String.Concat(hashedPwd, salt);
			return hashedPwd;
		}

		public static string GetHashedValue(string value, CryptoAlgorithmType algoType = CryptoAlgorithmType.SHA1)
		{
			string hashValue = string.Empty;
			switch (algoType)
			{
				case CryptoAlgorithmType.SHA1:
					hashValue = GetSHA1(value);
					break;
				case CryptoAlgorithmType.SHA256:
					hashValue = GetSHA256(value);
					break;
#if(!SILVERLIGHT)
				case CryptoAlgorithmType.MD5:
					hashValue = GetMD5(value);
					break;
				case CryptoAlgorithmType.SHA384:
					hashValue = GetSHA384(value);
					break;
				case CryptoAlgorithmType.SHA512:
					hashValue = GetSHA512(value);
					break;
#endif
				default:
					hashValue = GetSHA1(value);
					break;
			}

			return hashValue;
		}

		public static string GetSHA1(string value)
		{
			SHA1 algorithm = default(SHA1);
#if(SILVERLIGHT)
			algorithm = new SHA1Managed();
#else
			algorithm = SHA1.Create();
#endif

			byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
			return ByteArrayToHexString(data);
		}

		public static string GetSHA256(string value)
		{
			SHA256 algorithm = default(SHA256);

#if(SILVERLIGHT)
			algorithm = new SHA256Managed();
#else
			algorithm = SHA256.Create();
#endif

			byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
			return ByteArrayToHexString(data);
		}

#if(!SILVERLIGHT)
		public static string GetSHA384(string value)
		{
			SHA384 algorithm = SHA384.Create();
			byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
			return ByteArrayToHexString(data);
		}

		public static string GetSHA512(string value)
		{
			SHA512 algorithm = SHA512.Create();
			byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
			return ByteArrayToHexString(data);
		}

		public static string GetMD5(string value)
		{
			MD5 algorithm = MD5.Create();
			byte[] data = algorithm.ComputeHash(Encoding.UTF8.GetBytes(value));
			return ByteArrayToHexString(data);
		}
#endif

		static string ByteArrayToHexString(byte[] data)
		{
			string retVal = "";
			for (int i = 0; i < data.Length; i++)
				retVal += data[i].ToString("x2").ToLowerInvariant();

			return retVal;
		}
	}
}
